/**
	@file Parser.h
	@brief This file contains InputParser class definition along with helpful classes and enums.
*/
#pragma once
#ifndef __PARSER_H__
#define __PARSER_H__ 

#include <fstream>
#include <sstream>
#include "../common/DataType.h"
#include "../storage/Storage.h"
namespace LightChart
{
	/**
		@var SeriesOrientation
		@brief Describes whether next values in input file are laid out in columns (VERTICAL_SERIES) or in rows (HORIZONTAL_SERIES). 
	*/
    enum SeriesOrientation
    {
	VERTICAL_SERIES = 0x1A,
    	HORIZONTAL_SERIES
    };
     /**
     	@class Conversion
     	@author Maciej Siczek
     	@version 1.0a
     	@brief Stores conversion's results: success state, and converted value.
     */
    class Conversion
    {
    	public:
    	Conversion() {}
    	Conversion(bool b, double d) : success(b), value(d) {}
    	operator bool() const { return success;	}
    	bool operator!() const { return !success; }
    	double val() const { return value; }
    	private:
    	bool success;
    	double value;
    };
   	/**
    	@class InputParser
    	@author Maciej Siczek
    	@version 1.0a
    	@brief Reads data from file and stores everything in Storage class
    
    	It copes with different data layouts.
    */ 
    class InputParser
    {
    	public:
    	InputParser(); ///< default constructor
    	~InputParser(); ///< destructor
    	bool prepareFile() throw(boost::bad_get); ///< Prepares file by cutting off its header and footer (if exist). In case of VERTICAL_SERIES it reads and stores data series' labels. At the end it call readFile().
	/**
		@brief Parse file that is prepared before by prepareFile()
		@return parsing success state.
		@throws boost::bad_get
	*/
    	bool readFile() throw(boost::bad_get);
	/**
		@brief Sets orientation
		@param so new orientation
	*/
    	void setOrientation(SeriesOrientation so) { seriesOrientation = so; }
	/**
		@brief Sets header's containment information
		@param b header's presence. True if present.
	*/
    	void setHeader(bool b) { containsHeader = b; }
	/**
		@brief Sets footer's containment information
		@param b footer's presence. True if present.
	*/
    	void setFooter(bool b) { containsFooter = b; }
	/**
		@brief Checks whether single portion of information read from input file can be converted to numeric type or not.
		@param s portion of information
		@return Conversion results
	*/
    	Conversion isNumber(const std::string& s);
	/**
		@brief Controlls parsing.
		@param s storage pointer
		@param fn full file's name
		@param so serie's orientation
		@param h header's presence
		@param f footer's presence
		@param l series labels' presence
		@return parsing success state

		Opens and closes file, sets parsing flags, initializes parsing by calling prepareFile(). 
	*/
    	bool parse(Storage* s, const char* fn, SeriesOrientation so = HORIZONTAL_SERIES, bool h = false, bool f = false, bool l = false);
    	private:
    	bool containsHeader;
    	bool containsFooter;
    	bool labels;
    	std::streampos from;
    	std::streampos to;
    	unsigned nrOfSeries;
    	SeriesOrientation seriesOrientation;
    	std::ifstream file;
    	std::ofstream of;
	Storage *storage;
    };
} /* LightChart */

#endif /* __PARSER_H__ */
